<template>
  <div :id="id" class="chart-popup">
    <button class="close-chart-btn" @click="closePopup">&times;</button>
    <canvas :id="canvasId"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch, computed, nextTick } from 'vue'
import Chart from 'chart.js/auto' // 确保正确导入 Chart.js
import 'chartjs-plugin-annotation' // 确保导入标注插件

const props = defineProps({
  id: {
    // 接收弹窗的完整ID，例如 'chartPopupFIC1007'
    type: String,
    required: true,
  },
  sensorId: {
    // 接收传感器的唯一标识/点位名称，例如 'FIC1007'
    type: String, // 根据后端期望，这里应该是字符串
    required: true,
  },
})

// 计算 canvas 元素的 ID
const canvasId = computed(() => `sensorChartCanvas-${props.sensorId}`) // 为避免与 popupId 混淆，加上 -Canvas 后缀
let sensorChartInstance = null // 用于存储 Chart 实例

/**
 * 关闭弹窗并销毁图表实例。
 */
const closePopup = () => {
  const popup = document.getElementById(props.id)
  if (popup) {
    popup.style.display = 'none' // 隐藏弹窗
  }
  destroyChart() // 销毁图表
}

/**
 * 销毁 Chart.js 实例，释放资源。
 */
const destroyChart = () => {
  if (sensorChartInstance) {
    sensorChartInstance.destroy()
    sensorChartInstance = null
    console.log(`SensorChartPopup: Chart instance for ${props.sensorId} destroyed.`)
  }
}

/**
 * 从后端获取传感器历史和预测数据。
 * @returns {Promise<Object>} 包含 labels, historicalChartData, predictedChartData 的对象。
 */
const fetchSensorData = async () => {
  try {
    // props.sensorId 已经是后端期望的完整点位名称，直接使用
    const pointName = props.sensorId
    console.log(`SensorChartPopup: Fetching data for point: ${pointName}`)

    const response = await fetch(`/api/get_point_data?point=${pointName}`)

    if (!response.ok) {
      const errorText = await response.text()
      throw new Error(
        `Failed to fetch sensor data for ${pointName}: ${response.status} ${response.statusText} - ${errorText}`,
      )
    }
    const data = await response.json()
    console.log(`SensorChartPopup: Received data for ${pointName}:`, data)

    if (!data.success) {
      throw new Error(
        `API returned success: false - ${data.message || 'Unknown error'} for point ${pointName}`,
      )
    }

    // 解析历史数据
    const historicalLabels = data.history.map((item) => {
      return new Date(item.datetime).toLocaleTimeString([], {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
      })
    })
    const historicalData = data.history.map((item) => item.value)

    // 解析预测数据
    const predictedLabels = data.predict.map((item) => {
      return new Date(item.datetime).toLocaleTimeString([], {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
      })
    })
    const predictedData = data.predict.map((item) => item.value)

    // 将历史数据和预测数据合并成适合 Chart.js 的数据结构
    // 确保预测数据从历史数据的末尾开始，使用 null 填充断开连接
    const allLabels = [...historicalLabels]
    const historicalChartData = [...historicalData]
    // 预测曲线的起始点与历史曲线的终点重合
    const predictedChartData = Array(historicalData.length - 1).fill(null)
    if (historicalData.length > 0) {
      predictedChartData.push(historicalData[historicalData.length - 1])
    } else {
      // 如果没有历史数据，预测数据也从空开始
      predictedChartData.push(null)
    }

    for (let i = 0; i < predictedLabels.length; i++) {
      allLabels.push(predictedLabels[i])
      predictedChartData.push(predictedData[i])
    }

    return {
      labels: allLabels,
      historicalChartData: historicalChartData,
      predictedChartData: predictedChartData,
    }
  } catch (error) {
    console.error(`SensorChartPopup: Error fetching data for ${props.sensorId}:`, error)
    // 在出错时，返回空数据，图表将显示警告信息
    return { labels: [], historicalChartData: [], predictedChartData: [] }
  }
}

/**
 * 绘制传感器数据折线图。
 */
const drawSensorChart = async () => {
  destroyChart() // 确保销毁旧图表实例

  const canvasElement = document.getElementById(canvasId.value)
  if (!canvasElement) {
    console.error(
      `SensorChartPopup: Canvas element not found for ID: ${canvasId.value}. Cannot draw chart.`,
    )
    return
  }
  const ctx = canvasElement.getContext('2d')
  if (!ctx) {
    console.error(`SensorChartPopup: Could not get 2D context for canvasId: ${canvasId.value}.`)
    return
  }
  console.log(`SensorChartPopup: Canvas context obtained for ${props.sensorId}.`)

  const { labels, historicalChartData, predictedChartData } = await fetchSensorData()

  if (labels.length === 0) {
    console.warn(`SensorChartPopup: No data to display for sensor ${props.sensorId} chart.`)
    // 可以在这里显示一个“无数据”的提示
    ctx.clearRect(0, 0, canvasElement.width, canvasElement.height) // 清空canvas
    ctx.font = '16px Arial'
    ctx.fillStyle = '#888'
    ctx.textAlign = 'center'
    ctx.fillText('暂无数据', canvasElement.width / 2, canvasElement.height / 2)
    return
  }

  // 动态设置Y轴的最小值和最大值
  // 确保过滤掉 null 值，只对数值进行 min/max 计算
  const allNumericalData = [...historicalChartData, ...predictedChartData].filter(
    (v) => typeof v === 'number' && v !== null,
  )
  let minValue = allNumericalData.length > 0 ? Math.min(...allNumericalData) : 0
  let maxValue = allNumericalData.length > 0 ? Math.max(...allNumericalData) : 100

  // 确保 Y 轴有足够的范围，即使数据点很少
  if (minValue === maxValue) {
    minValue -= 5 // 如果所有值都相同，给一个默认范围
    maxValue += 5
  }
  const padding = (maxValue - minValue) * 0.1 // 10%的上下边距

  sensorChartInstance = new Chart(ctx, {
    type: 'line',
    data: {
      labels: labels,
      datasets: [
        {
          label: '历史数据',
          data: historicalChartData,
          borderColor: 'rgb(54, 162, 235)', // 蓝色
          backgroundColor: 'rgba(54, 162, 235, 0.1)',
          borderWidth: 2,
          tension: 0.3,
          pointRadius: 0,
          fill: false,
          spanGaps: true, // 允许数据中的 null 值断开连接
        },
        {
          label: '预测数据',
          data: predictedChartData,
          borderColor: 'rgb(75, 192, 192)', // 绿色
          backgroundColor: 'rgba(75, 192, 192, 0.1)',
          borderWidth: 2,
          tension: 0.3,
          pointRadius: 0,
          fill: false,
          spanGaps: true, // 允许数据中的 null 值断开连接
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        title: {
          display: true,
          text: `传感器 ${props.sensorId} 数据趋势`, // 动态标题
          font: { size: 14 },
        },
        legend: {
          display: true,
          position: 'top',
        },
      },
      scales: {
        x: {
          display: true,
          title: {
            display: true,
            text: '时间',
          },
          ticks: {
            autoSkip: true,
            maxTicksLimit: 10,
          },
        },
        y: {
          display: true,
          title: {
            display: true,
            text: '参数值',
          },
          min: minValue - padding, // 动态设置Y轴最小值
          max: maxValue + padding, // 动态设置Y轴最大值
        },
      },
    },
  })
}

// 监听弹窗的显示状态，如果显示则绘制图表
// 1. 监听的是 popupElement 的实际 style.display 属性
// 2. 使用 nextTick 确保 DOM 已经完全更新，Canvas 元素可用
// 3. immediate: true 确保组件挂载时如果弹窗已经是可见状态，也能触发绘制
watch(
  // 监听一个函数，这个函数返回 `props.id` 对应 DOM 元素的 `style.display` 属性
  // 如果元素不存在，则返回 undefined
  () => {
    const el = document.getElementById(props.id)
    return el ? el.style.display : undefined
  },
  async (newDisplayValue) => {
    console.log(
      `SensorChartPopup (${props.sensorId}): Watcher detected display change. New value: ${newDisplayValue}`,
    )
    if (newDisplayValue === 'flex') {
      // 使用 nextTick 确保在 Vue 更新 DOM 后再尝试获取 Canvas 上下文
      await nextTick()
      console.log(`SensorChartPopup (${props.sensorId}): nextTick triggered for 'flex' display.`)
      drawSensorChart()
    } else {
      // 可以在弹窗隐藏时销毁图表，节省资源
      destroyChart()
    }
  },
  { immediate: true }, // 确保在组件初始化时立即运行一次
)

// 组件卸载时销毁图表实例，防止内存泄漏
onUnmounted(() => {
  destroyChart()
})
</script>

<style scoped>
/*
 * 弹窗和 Canvas 的基本样式，确保 Canvas 有实际的尺寸
 * 这些样式通常在全局 style.css 中定义，这里仅作参考
 */
.chart-popup {
  position: absolute;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  padding: 15px;
  z-index: 20;
  width: 400px; /* 确保有固定宽度 */
  height: 250px; /* 确保有固定高度 */
  display: none; /* 初始隐藏 */
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.chart-popup .close-chart-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  background: none;
  border: none;
  font-size: 1.5em;
  cursor: pointer;
  color: #555;
  z-index: 21;
}

.chart-popup canvas {
  width: 100% !important; /* 确保 Canvas 填充父容器 */
  height: 100% !important;
}
</style>
